package com.jingsai.Scheduled;

import com.jingsai.POJO.Common.ScoreHistory;
import com.jingsai.POJO.Common.SubmitHistory;
import com.jingsai.POJO.Common.TodayProblemId;
import com.jingsai.POJO.Common.UserScore;
import com.jingsai.Service.Service;
import lombok.RequiredArgsConstructor;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.util.EntityUtils;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.Duration;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@Component
@RequiredArgsConstructor
public class ScheduledTask {
    private final Service service;
    Map<String,Integer>mp=new HashMap<>();
    //定时任务，保存数据
    @Scheduled(cron = "0 1 0 * * ?")
    public void task() throws IOException, ParseException {
        ArrayList<SubmitHistory> resultList = new ArrayList<>();
        SubmitHistory submitHistory = null;
        List<TodayProblemId> nw = service.selectProblemId();
        int ContestId = nw.get(0).getProblemId();
        String tmp = "http://124.222.52.164/status.php?cid=";
        String tmp1 = "";
        while (ContestId != 0) {
            tmp1 += (char) ((ContestId % 10) + (int) ('0'));
            ContestId = ContestId / 10;
        }
        tmp1 = new StringBuffer(tmp1).reverse().toString();
        tmp += tmp1;
        String Csstring = tmp;
        //easy
        int lastid = service.selectSubmitLast().get(0).getSubmitId();
        while (true) {
            int ok = 0;
            String page;
            page = connectToOJ(tmp);
            Pattern p = Pattern.compile("<a[^\\n]+[\\s]+下一页[\\s]+</a>");
            Matcher m = p.matcher(page);
            ArrayList<String> arrayList = collectContexts(page);//当前50条信息，未处理
            for (String str : arrayList) {//当前页50条倒序，加入list
                submitHistory = solve(str);//处理一条
                if (submitHistory.getSubmitItem() <= lastid) {
                    ok = 1;
                    break;
                }
                resultList.add(submitHistory);
            }
            if (ok == 1) break;

            while (m.find()) {
                String group = m.group();
                int Siz = group.length();
                tmp = Csstring;
                int Cnt = 0;
                for (int i = 0; i < Siz; i++) {
                    if (group.charAt(i) == '&') Cnt++;
                    if (group.charAt(i) == '&' && Cnt == 2) {
                        int j = i;
                        while (j < Siz && group.charAt(j) != '"') {
                            tmp += group.charAt(j);
                            j++;
                        }
                        break;
                    }
                }
            }
            if (arrayList.size() == 1) break;
        }
        Collections.reverse(resultList);

        List<TodayProblemId> selectProblemId = service.selectProblemId();
        Date date = selectProblemId.get(0).getProblemDate();
        int Lid = 0;
        for (SubmitHistory mes : resultList) {
            if (mes.getSubmitItem() == Lid) continue;

            Lid = mes.getSubmitItem();
            lastid = mes.getSubmitItem();
            calc(mes, date);
        }

        service.updateSubmitLast(lastid);

    }


    private void calc(SubmitHistory mes, Date date) {

        if (mes.getUserInfo().length() == 10 && mes.getUserInfo().charAt(0) == '2' && mes.getUserInfo().charAt(1) == '4') {
            service.insertSubmitHistory(mes);
            int EasyId = 0;
            int HardId = 1;
            if (mes.getSubmitTime().equals(date)) {
                int Reinfo = mes.getReinfo();
                String user_info = mes.getUserInfo();
                List<ScoreHistory> list = service.selectScoreHistoryBy_user_infoAndDate(user_info,date);
                if (mes.getProblem() == EasyId) {
                    if (list.size() == 0) {
                        ScoreHistory sc = new ScoreHistory();
                        sc.setUserInfo(user_info);
                        sc.setUserName(mes.getUserName());
                        sc.setSubmitTime(mes.getSubmitTime());
                        sc.setIsSubmit(1);
                        sc.setIstrueEasy(Reinfo);
                        sc.setIstrueHard(0);
                        service.insertScoreHistory(sc);
                        UpdateUserScoer(sc);
                    }
                    else {
                        ScoreHistory sc = list.get(0);
                        if (Reinfo == 1)
                        {
                            sc.setIstrueEasy(1);
                            service.updateScoreHistory(sc);
                        }
                        UpdateUserScoer(sc);

                    }
                } else if (mes.getProblem() == HardId) {
                    if (list.size() == 0) {
                        ScoreHistory sc = new ScoreHistory();
                        sc.setUserInfo(user_info);
                        sc.setUserName(mes.getUserName());
                        sc.setSubmitTime(mes.getSubmitTime());
                        sc.setIsSubmit(1);
                        sc.setIstrueHard(Reinfo);
                        sc.setIstrueEasy(0);
                        service.insertScoreHistory(sc);
                        UpdateUserScoer(sc);
                    }
                    else {
                        ScoreHistory sc = list.get(0);
                        if (Reinfo == 1)
                        {
                            sc.setIstrueHard(1);
                            service.updateScoreHistory(sc);
                        }
                        UpdateUserScoer(sc);
                    }
                }
            }
        }
    }

    private void UpdateUserScoer(ScoreHistory sc) {
        String user_info = sc.getUserInfo();
        List<UserScore> list = service.selectUserScoreBy_user_info(user_info);
        if(list.size()==0){
            UserScore us=new UserScore();
            us.setUserInfo(user_info);
            us.setUserName(sc.getUserName());
            us.setFullscoreDay(0);
            us.setSevendayFullscore(0);
            us.setTodayFirstac(0);
            us.setLastSubmitDate(sc.getSubmitTime());
            if(sc.getIsSubmit()==1)us.setLastScore(1);
            if(sc.getIstrueEasy()==1)us.setLastScore(5);
            if(sc.getIstrueHard()==1)us.setLastScore(10);
            if(sc.getIstrueEasy()==1&&sc.getIstrueHard()==1)us.setLastScore(15);

            String New;
            if(sc.getIstrueEasy()==1){
                New=sc.getSubmitTime().toString();
                New+='0';
                if(!mp.containsKey(New)){
                    us.setTodayFirstac(us.getTodayFirstac()+1);
                    mp.put(New,1);
                }
            }

            if(sc.getIstrueHard()==1){
                New=sc.getSubmitTime().toString();
                New+='1';
                if(!mp.containsKey(New)){
                    us.setTodayFirstac(us.getTodayFirstac()+1);
                    mp.put(New,1);
                }
            }
            if(us.getLastScore()==15){
                us.setFullscoreDay(1);
                us.setLastFullscore(sc.getSubmitTime());
            }
            us.setScoreSum(us.getLastScore()+us.getTodayFirstac()*5);
            service.insertUserScore(us);
        }
        else {
            UserScore us=list.get(0);
            if(us.getLastSubmitDate().equals(sc.getSubmitTime())){//不是今天第一条
                us.setScoreSum(us.getScoreSum()-us.getLastScore()-us.getTodayFirstac()*5);

                us.setLastScore(0);
                if(sc.getIsSubmit()==1)us.setLastScore(1);
                if(sc.getIstrueEasy()==1)us.setLastScore(5);
                if(sc.getIstrueHard()==1)us.setLastScore(10);
                if(sc.getIstrueEasy()==1&&sc.getIstrueHard()==1)us.setLastScore(15);
                String New;
                if(sc.getIstrueEasy()==1){
                    New=sc.getSubmitTime().toString();
                    New+='0';
                    if(!mp.containsKey(New)){
                        us.setTodayFirstac(us.getTodayFirstac()+1);
                        mp.put(New,1);
                    }
                }

                if(sc.getIstrueHard()==1){
                    New=sc.getSubmitTime().toString();
                    New+='1';
                    if(!mp.containsKey(New)){
                        us.setTodayFirstac(us.getTodayFirstac()+1);
                        mp.put(New,1);
                    }
                }

                if(us.getLastScore()==15){
                    if(us.getLastFullscore()!= null && date_xl(us.getLastFullscore(),sc.getSubmitTime())==1) {
                        us.setFullscoreDay(us.getFullscoreDay()+1);
                    }
                    else if(us.getFullscoreDay()!= null && us.getFullscoreDay().equals(sc.getSubmitTime())){

                    }
                    else {
                        us.setFullscoreDay(1);
                    }
                    us.setLastFullscore(sc.getSubmitTime());
                }
                us.setScoreSum(us.getScoreSum()+us.getLastScore()+us.getTodayFirstac()*5);
                if(us.getSevendayFullscore()==0&&us.getFullscoreDay()>=7){
                    us.setSevendayFullscore(1);
                    us.setScoreSum(us.getScoreSum()+25);
                }

                service.updateUserScore(us);


            }
            else{//今天的第一条
                UserScore userScore=new UserScore();
                userScore.setUserInfo(user_info);
                userScore.setUserName(sc.getUserName());
                userScore.setFullscoreDay(us.getFullscoreDay());
                userScore.setSevendayFullscore(us.getSevendayFullscore());
                userScore.setTodayFirstac(0);
                userScore.setLastFullscore(us.getLastFullscore());
                userScore.setLastSubmitDate(sc.getSubmitTime());

                if(sc.getIsSubmit()==1)userScore.setLastScore(1);
                if(sc.getIstrueEasy()==1)userScore.setLastScore(5);
                if(sc.getIstrueHard()==1)userScore.setLastScore(10);
                if(sc.getIstrueEasy()==1&&sc.getIstrueHard()==1)userScore.setLastScore(15);

                String New;
                if(sc.getIstrueEasy()==1){
                    New=sc.getSubmitTime().toString();
                    New+='0';
                    if(!mp.containsKey(New)){
                        userScore.setTodayFirstac(userScore.getTodayFirstac()+1);
                        mp.put(New,1);
                    }
                }

                if(sc.getIstrueHard()==1){
                    New=sc.getSubmitTime().toString();
                    New+='1';
                    if(!mp.containsKey(New)){
                        userScore.setTodayFirstac(userScore.getTodayFirstac()+1);
                        mp.put(New,1);
                    }
                }

                if(userScore.getLastScore()==15){

                    if(us.getLastFullscore()!= null && date_xl(us.getLastFullscore(),sc.getSubmitTime())==1) {
                        userScore.setFullscoreDay(us.getFullscoreDay()+1);
                    }
                    else {
                        userScore.setFullscoreDay(1);
                    }
                    userScore.setLastFullscore(sc.getSubmitTime());
                }

                userScore.setScoreSum(us.getScoreSum()+userScore.getLastScore()+userScore.getTodayFirstac()*5);

                if(userScore.getSevendayFullscore()==0&&userScore.getFullscoreDay()>=7){
                    userScore.setSevendayFullscore(1);
                    userScore.setScoreSum(userScore.getScoreSum()+25);
                }
                service.updateUserScore(userScore);
            }
        }
    }

    private int date_xl(Date d1,Date d2){
        LocalDateTime l1 = d1.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
        LocalDateTime l2 = d2.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
        if(l2.isAfter(l1)){
            Duration between = Duration.between(l1, l2);
            if(between.toDays()==1)return 1;
            else return 0;
        }
        else return 0;
    }

    private SubmitHistory solve(String Context) throws ParseException {
        SubmitHistory mes = new SubmitHistory();
        int ok = 0;
        int oktitle = 0;
        int okproblemid = 0;
        int Size = Context.length();
        for (int i = 0; i < Size; i++) {
            if (ok == 0 && i + 2 < Size && Context.charAt(i) == '<' && Context.charAt(i + 1) == 'b' && Context.charAt(i + 2) == '>') {
                ok = 1;
                int j = i + 3;
                int res = 0;//提交编号
                while (j < Size && Context.charAt(j) >= '0' && Context.charAt(j) <= '9') {
                    res = res * 10 + (Context.charAt(j) - '0');
                    j++;
                }
                mes.setSubmitItem(res);
            }
            if (oktitle == 0 && i + 20 < Size) {
                String Title = "";
                for (int j = i; j < i + 20; j++) Title += Context.charAt(j);
                if (Title.equals("</a></b></td><td><b>")) {
                    String res = "";//用户昵称
                    int j = i + 20;
                    while (j + 3 < Size) {
                        if (Context.charAt(j) == '<' && Context.charAt(j + 1) == '/' && Context.charAt(j + 2) == 'b' && Context.charAt(j + 3) == '>')
                            break;
                        j++;
                    }
                    res = Context.substring(i + 20, j);
                    oktitle = 1;
                    mes.setUserName(res);
                }

            }
            if (okproblemid == 0 && i + 3 < Size) {
                String Problemid = "";
                for (int j = i; j < i + 3; j++) Problemid += Context.charAt(j);
                if (Problemid.equals("id=") && Context.charAt(i-1)!='_') {
                    int res = 0;//题目编号
                    int j = i + 3;
                    while (j < Size && Context.charAt(j) != '>') j++;
                    j++;
                    if (Context.charAt(j) != 'A'&&Context.charAt(j)!='B') {}
                    else if(Context.charAt(j)=='A'){
                        res = 0;
                        mes.setProblem(res);
                        okproblemid = 1;
                    }
                    else if(Context.charAt(j)=='B'){
                        res=1;
                        mes.setProblem(res);
                        okproblemid = 1;
                    }
                }
            }

            {
                String tmp = "";
                for (int j = i; j < Math.min(i + 8, Size); j++) tmp += Context.charAt(j);
                if (tmp.equals("user_id=")) {
                    int j = i + 8;
                    String res = "";//用户名（学号） 学号必须是10位并且以24开头
                    while (j < Size && Context.charAt(j) >= '0' && Context.charAt(j) <= '9') {
                        res += Context.charAt(j);
                        j++;
                    }
                    mes.setUserInfo(res);
                }
            }

            {
                String tmp = "";
                for (int j = i; j < Math.min(i + 7, Size); j++) tmp += Context.charAt(j);
                if (tmp.equals("result=")) {
                    int j = i + 7;
                    int res = 0;
                    while (j < Size && Context.charAt(j) != '>') {
                        res = res * 10 + (Context.charAt(j) - '0');
                        j++;
                    }

                    if (res == 4) mes.setReinfo(1);
                    else mes.setReinfo(0);
                }
            }
        }

        String NowTime = "";
        int j = Size - 15;
        while (j > 0 && Context.charAt(j) != '>') {
            NowTime += Context.charAt(j);
            j--;
        }
        NowTime = new StringBuffer(NowTime).reverse().toString();//提交时间
        int lens = 9;
        while (lens > 0) {
            NowTime = NowTime.substring(0, NowTime.length() - 1);
            lens--;
        }
//        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
//        LocalDate localDate = LocalDate.parse(NowTime, formatter);
//        Date sqlDate = Date.valueOf(localDate);
//        mes.setSubmitTime(sqlDate);
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        Date date = format.parse(NowTime);
        mes.setSubmitTime(date);
        return mes;
    }

    //连接获取提交信息
    private String connectToOJ(String Url) throws IOException {
        CloseableHttpClient httpClient = HttpClientBuilder.create().build();
        HttpGet httpGet = new HttpGet(Url);
        CloseableHttpResponse response;
        response = httpClient.execute(httpGet);
        String result = null;
        try {
            //4.处理结果，这里将结果返回为字符串
            HttpEntity entity = response.getEntity();
            if (entity != null) {
                result = EntityUtils.toString(entity);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                response.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return result;
    }

    //获取条目页面信息
    private ArrayList<String> collectContexts(String page) {
        String context = "";
        ArrayList<String> resultList = new ArrayList<String>();
        Pattern p = Pattern.compile("<tbody>[\\s\\S]+</tbody>");
        Matcher m = p.matcher(page);
        while (m.find()) context = m.group();
        p = Pattern.compile("<tr>([\\s\\S]*?)</tr>");
        m = p.matcher(context);
        while (m.find()) {
            String group = m.group(0);
            if (!"".equals(group)) {
                resultList.add(group);
            }
        }
        return resultList;
    }
}